package gsw.tool.common;

import android.os.Handler;
import android.os.Looper;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * 网络工具类
 * 使用OkHttp框架：implementation 'com.squareup.okhttp3:okhttp:3.10.0'
 */
public class ToolHttp {
    private static ToolHttp mInstance;
    private OkHttpClient mOkHttpClient;
    private Handler mDelivery;
    private static FormBody.Builder bodyBuilder;
    private static Map<String, String> soapParams;//ebservice请求数据

    private ToolHttp() {
        mOkHttpClient = new OkHttpClient.Builder()
                .addInterceptor(new LoggingInterceptor())
                .connectTimeout(15, TimeUnit.SECONDS)
                .readTimeout(20, TimeUnit.SECONDS)
                .writeTimeout(20, TimeUnit.SECONDS)
                .build();
        mDelivery = new Handler(Looper.getMainLooper());
    }

    public static ToolHttp build() {
        if (mInstance == null) {
            synchronized (ToolHttp.class) {
                if (mInstance == null) {
                    mInstance = new ToolHttp();
                }
            }
        }
        bodyBuilder = null;
        soapParams = null;
        return mInstance;
    }

    //get异步请求
    public void get(String url, StringCallback callback) {
        Request request = new Request.Builder().url(url).build();
        deliveryResult(callback, request);
    }

    //post异步请求
    public void post(String url, StringCallback callback) {
        RequestBody body = bodyBuilder.build();
        Request request = new Request.Builder().url(url).post(body).build();
        deliveryResult(callback, request);
    }

    //添加参数
    public ToolHttp addParams(String key, String value) {
        if (bodyBuilder == null) {
            bodyBuilder = new FormBody.Builder();
        }
        bodyBuilder.add(key, value);
        return mInstance;
    }

    //webServices的post异步请求
    public void webPost(String url, String methodName, StringCallback callback) {
        MediaType type = MediaType.parse("text/xml;charset=UTF-8");
        RequestBody body = RequestBody.create(type, getSoapRequestData(methodName, soapParams));
        Request request = new Request.Builder().url(url).post(body).build();
        deliveryResult(callback, request);
    }

    //添加参数
    public ToolHttp addSoapParams(String key, String value) {
        if (soapParams == null) {
            soapParams = new HashMap<>();
        }
        soapParams.put(key, value);
        return mInstance;
    }

    //凑成xml格式字符串
    public String getSoapRequestData(String methodName, Map params) {
        StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
        sb.append("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " +
                "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">");
        sb.append("<soap:Body>");
        sb.append("<" + methodName + " xmlns=\"http://tempuri.org/\">");
        Iterator it = params.keySet().iterator();
        while (it.hasNext()) {
            String key = (String) it.next();
            String value = (String) params.get(key);
            sb.append("<" + key + ">" + value + "</" + key + ">");
        }
        sb.append("</" + methodName + ">");
        sb.append("</soap:Body>");
        sb.append("</soap:Envelope>");
        String s = sb.toString();
        return s;
    }

    //UI线程处理结果
    private void deliveryResult(final StringCallback callback, Request request) {
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(final Call call, final IOException e) {
                mDelivery.post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onFailure(call, e);
                    }
                });
            }

            @Override
            public void onResponse(final Call call, Response response) throws IOException {
                final String s = response.body().string();
                response.close();
                mDelivery.post(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            callback.onResponse(call, s);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        });
    }


    /**
     * 网络拦截器
     */
    public static class LoggingInterceptor implements Interceptor {
        @Override
        public Response intercept(Interceptor.Chain chain) throws IOException {
            Request request = chain.request();

            long t1 = System.nanoTime();
            ToolShow.log(String.format("Sending request %S on %S%n%S",
                    request.url(), chain.connection(), request.headers()));

            Response response = chain.proceed(request);

            long t2 = System.nanoTime();
            ToolShow.log(String.format("Received response for %S in %.1fms%n%S",
                    response.request().url(), (t2 - t1) / 1e6d, response.headers()));
            request = response.networkResponse().request();
            ToolShow.log(String.format("Sending request2 %S on %S%n%S",
                    request.url(), chain.connection(), request.headers()));

            return response;
        }
    }

    /**
     * 回调函数
     */
    public static interface StringCallback {

        void onFailure(Call call, IOException e);

        void onResponse(Call call, String response) throws IOException;
    }
}
